/**
 * 
 */
package trungsi.gea.photos.service;

import static trungsi.gea.photos.util.PhotoUtils.resize;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.cache.Cache;

import org.springframework.beans.factory.annotation.Autowired;

import trungsi.gea.photos.dao.PhotoDao;
import trungsi.gea.photos.domain.Folder;
import trungsi.gea.photos.domain.Photo;
/**
 * @author trungsi
 *
 */
// cannot use this because cache obj (which is factory bean) is not injected
//@Service
public class PhotoService {

	private static final Logger log = Logger.getLogger(PhotoService.class.getName());
	
	@Autowired
	private PhotoDao photoDao;
	
	private Cache cache;
	
	public void setCache(Cache cache) {
		this.cache = cache;
	}
	
	public void save(Photo photo) {
		if (photo.getThumbnail() == null) {
			photo.setThumbnail(resize(photo.getPhoto(), 100));
		}
		if (photo.getSlideshow() == null) {
			photo.setSlideshow(resize(photo.getPhoto(), 800));
		}
		
		photoDao.save(photo);
		
		clearCache();
	}

	private void clearCache() {
		try {
			cache.clear();
		} catch (Exception e) {
			log.log(Level.WARNING, "cannot clear cache", e);
		}
	}

	public void delete(Photo photo) {
		photoDao.delete(photo);

		clearCache();
	}

	/*public void deleteAll() {
		deleteAll(photoDao.findAll());

		cache.clear();
	}*/

	private void deleteAll(List<Photo> photos) {
		for (Photo photo : photos) {
			photoDao.delete(photo);
		}
	}

	public List<Photo> findAllByFolder(Folder folder, Date date, int limit) {
		List<Photo> photos = (List<Photo>) cache.get(getKey(folder, date, limit));
		if (photos == null) {
			photos = photoDao.findByFolder(folder, date, limit);
			addToCache(getKey(folder, date, limit), new ArrayList<Photo>(photos));
		}
		
		return photos;
		
	}

	private void addToCache(Object key, Object value) {
		try {
			cache.put(key, value);
		} catch (Exception e) {
			log.log(Level.WARNING, "cannot clear cache", e);
		}
	}

	private Object getKey(Folder folder, Date date, int limit) {
		return folder.getId() + "_" + (date != null ? date.getTime() : 0) + "_" + limit;
	}

	public List<Photo> findAllByFolder(Folder folder, int limit) {
		List<Photo> photos = null;
		try {
			photos = (List<Photo>) cache.get(getKey(folder, null, limit));
		} catch (Exception e) {
			log.log(Level.WARNING, "cannot get from cache", e);
		}
		if (photos == null) {
			photos = photoDao.findByFolder(folder, limit);
			addToCache(getKey(folder, null, limit), new ArrayList<Photo>(photos));
		}
		
		return photos;
	}

	public int countByFolder(Folder folder) {
		return photoDao.countByFolder(folder);
	}

	public Photo getFirstPhoto(Folder folder) {
		List<Photo> photos = photoDao.findByFolder(folder, 1);
		return photos.isEmpty() ? null : photos.get(0);
	}

	public void deleteAll(Folder folder) {
		List<Photo> photos = findAllByFolder(folder, 20);
		while (!photos.isEmpty()) {
			deleteAll(photos);
			clearCache();
			photos = findAllByFolder(folder, 20);
		}
	}
}
